import React, {memo, useMemo, useState} from 'react';

const HelloWorld = memo((props) => {
  console.log("HelloWorld被渲染");
  return (
      <div>
        <h2>{props.message}</h2>
      </div>
  )
})

function calcNumTotal(num) {
  console.log("calcNumTotal被调用")
  let total = 0;
  for (let i = 1; i <= num; i++) {
    total += i;
  }
  return total;
}

const App = memo(() => {
  const [counter, setCounter] = useState(0);
  const [limit, setLimit] = useState(0);
  const [message, setMessage] = useState('你好啊, 李银河')

  //问题：当组件重新渲染时, 当前函数组件会从上到下重新执行一次, 这时calcNumTotal函数的计算过程也会被重新执行！
  // const result = calcNumTotal(50);

  //优化点1：
  //useMemo: 针对函数返回值进行优化, 将函数执行结果的返回值进行缓存，每次返回同一个结果
  //useCallback: 针对函数本身进行优化, 将函数体的定义进行缓存, 每次返回相同的函数
  const result = useMemo(() => {
    return calcNumTotal(limit);
    //添加要依赖的 state, 只有当依赖的 state 发生改变时，才对内部函数进行重新计算
  }, [limit]);

  //问题：每一次当前组件重新渲染时，该对象都会被重新定义，会导致依赖该对象的子组件也跟着重新渲染
  // （值类型是没有区别的, 只有对象类型是会被重新定义）
  // const info = {name: 'why', age: 18};

  //优化点2：使用useMemo对子组件渲染进行优化
  //使用 useMemo，缓存对象数据，每次重新渲染返回的都是同一个 info 对象
  const info = useMemo(() => {
    return {name: 'why', age: 18};
  }, [])

  return (
      <div>
        <h2>计算结果: {result}</h2>
        <h2>limit: {limit}</h2>
        <button onClick={() => setLimit(limit + 1)}>+1</button>
        <h2>计数器: {counter}</h2>
        <button onClick={() => setCounter(counter + 1)}>+1</button>
        <HelloWorld message={message} info={info}/>
      </div>
  );
});

export default App;